//
// Created by Ivor_ on 2022/1/17.
//

#ifndef PHYSICAL_COMPUTING_PACKAGE_PLOTBMP_H
#define PHYSICAL_COMPUTING_PACKAGE_PLOTBMP_H

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>

typedef struct {
    unsigned int height;
    unsigned int width;
    unsigned int occupy;
    FILE* bmpFp;
} STDbmp;

typedef struct {
    unsigned char red;
    unsigned char green;
    unsigned char blue;
} PIXEL;

STDbmp* createNewBmp(char* fileName, unsigned int width, unsigned int height, PIXEL background);
void bmpDrawHorizontalLine(STDbmp* bmp, unsigned int locate, unsigned int thickness, unsigned int edge, PIXEL color);
void bmpDrawVerticalLine(STDbmp* bmp, unsigned int locate, unsigned int thickness, unsigned int edge, PIXEL color);
void bmpDrawPoint(STDbmp* bmp, unsigned int locateHorizontal, unsigned int locateVertical, unsigned int widthOfPoint, unsigned int heightOfPoint, PIXEL color);
void bmpClose(STDbmp* bmp);

struct bmpBasicOperate {
    STDbmp* (*new)(char*, unsigned int, unsigned int, PIXEL);
    void (*drawLine)(STDbmp*, unsigned int, unsigned int, unsigned int, PIXEL);
    void (*drawRow)(STDbmp*, unsigned int, unsigned int, unsigned int, PIXEL);
    void (*drawPoint)(STDbmp*, unsigned int, unsigned int, unsigned int, unsigned int, PIXEL);
    void (*close)(STDbmp*);
};

struct bmpBasicOperate bmpBO(void);

typedef struct {
    double xStart;
    double xEnd;
    double yStart;
    double yEnd;
} SCALE;

void bmpPlotPoints(STDbmp* bmp, SCALE scale, unsigned int pointHorizontalThick, unsigned int pointVerticalThick, PIXEL color, _Bool connect, int countOfPoints, double** points);
void bmpPlotPointsIteration(STDbmp* bmp, SCALE scale, unsigned int pointHorizontalThick, unsigned int pointVerticalThick, PIXEL color, _Bool connect, int countOfPointsTimes2, ...);
void bmpPlotFunction(STDbmp* bmp, SCALE scale, double(*pFunction)(), double minimum, double maximum, unsigned int pointHorizontalThick, unsigned int pointVerticalThick, PIXEL color);
void bmpPlotInverseFunction(STDbmp* bmp, SCALE scale, double(*pInvFunction)(), double minimum, double maximum, unsigned int pointHorizontalThick, unsigned int pointVerticalThick, PIXEL color);

struct bmpPlot {
    void (*points)(STDbmp*, SCALE, unsigned int, unsigned int, PIXEL, _Bool, int, double**);
    void (*ptsIter)(STDbmp*, SCALE, unsigned int, unsigned int, PIXEL, _Bool, int, ...);
    void (*fun)(STDbmp*, SCALE, double(*)(), double, double, unsigned int, unsigned int, PIXEL);
    void (*invFun)(STDbmp*, SCALE, double(*)(), double, double, unsigned int, unsigned int, PIXEL);
};

struct bmpPlot bmpPlt(void);

void bmpFlipHorizontal(STDbmp* bmp);
void bmpFlipVertical(STDbmp* bmp);

struct bmpFlip {
    void(*hori)(STDbmp*);
    void(*vert)(STDbmp*);
};

struct bmpFlip bmpFlp(void);

#endif //PHYSICAL_COMPUTING_PACKAGE_PLOTBMP_H
